/*
 * File Name:               XProfiler.cs
 * 
 * Description:             普通类
 * Author:                  lisiyu <576603306@qq.com>

 * Create Date:             2017/06/26
 */


using System;
using System.Collections.Generic;
using UnityEngine;

public class XProfilerCellData
{
    public int TotalCount;          // 执行总次数
    public float MinCostTime;       // 单次最小耗时
    public float MaxCostTime;       // 单次最大耗时
    public float TotalCostTime;     // 总耗时
    public float AvgCostTime;       // 平均每次耗时

    public int FrameMaxCount;       // 最大单帧执行次数
    public float FrameMaxTime;      // 最大单帧执行耗时

    private int mFrameCount;        // 当前帧执行次数
    private float mFrameTime;       // 当前帧执行耗时
    public void update()
    {
        if (mFrameCount > FrameMaxCount) FrameMaxCount = mFrameCount;
        if (mFrameTime > FrameMaxTime) FrameMaxTime = mFrameTime;

        mFrameCount = 0;
        mFrameTime = 0;
    }

    public void add(float costTime)
    {
        TotalCount++;

        if (TotalCount == 1)
        {
            MinCostTime = costTime;
            MaxCostTime = costTime;
            TotalCostTime = costTime;
            AvgCostTime = costTime;
        }
        else
        {
            if (MinCostTime > costTime) MinCostTime = costTime;
            if (MaxCostTime < costTime) MaxCostTime = costTime;
            TotalCostTime += costTime;
            AvgCostTime = TotalCostTime / TotalCount;
        }

        mFrameCount++;
        mFrameTime += costTime;
    }

    public override string ToString()
    {
        return string.Format("执行总次数 {0}, 单次最小耗时 {1}, 单次最大耗时 {2}, 总耗时 {3}, 平均每次耗时 {4}, 最大单帧执行次数 {5}, 最大单帧执行耗时 {6}", TotalCount, MinCostTime * 1000, MaxCostTime * 1000, TotalCostTime * 1000, AvgCostTime * 1000, FrameMaxCount, FrameMaxTime * 1000);
    }

    public string ToCSVString()
    {
        return string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}", TotalCount, MinCostTime * 1000, MaxCostTime * 1000, TotalCostTime * 1000, AvgCostTime * 1000, FrameMaxCount, FrameMaxTime * 1000);
    }
}

public class XProfiler
{
#if XProfiler
    private static Dictionary<int, XProfilerCellData> mTotalDatas = new Dictionary<int, XProfilerCellData>();
    private static Stack<float> mSampleStacks = new Stack<float>();
    private static List<string> mTags = new List<string>();
    public static string debugReportUrl = "http://report.zhanng.org:10086/XProfilerReport";
#endif

    public static void update()
    {
#if XProfiler
        foreach (var item in mTotalDatas)
        {
            item.Value.update();
        }
#endif
    }

    public static void begin()
    {
#if XProfiler
        mSampleStacks.Push(Time.realtimeSinceStartup);
#endif
    }

    public static void end(System.Type tag)
    {
#if XProfiler
        end(tag.ToString());
#endif
    }

    public static void end<T>(T tag) where T : IFormattable
    {
#if XProfiler
        end(tag.ToString());
#endif
    }

    public static void end(string tag)
    {
#if XProfiler
        var now = Time.realtimeSinceStartup;
        var old = mSampleStacks.Pop();
        var costTime = now - old;

        var index = mTags.IndexOf(tag);
        if (index < 0)
        {
            mTags.Add(tag);
            index = mTags.Count - 1;
            mTotalDatas.Add(index, new XProfilerCellData());
        }

        mTotalDatas[index].add(costTime);
#endif
    }

    public static void over()
    {
#if XProfiler
        XLogHandler.Write2Console = true;
        var sb = new System.Text.StringBuilder();
        sb.AppendLine("Tag\t执行总次数\t单次最小耗时\t单次最大耗时\t总耗时\t平均每次耗时\t最大单帧执行次数\t最大单帧执行耗时");

        foreach (var item in mTotalDatas)
        {
            var tag = mTags[item.Key];
            if (item.Value.FrameMaxTime > 0.001f)
            {
                Debug.LogErrorFormat("{0}, {1}", tag, item.Value);
            }

            sb.AppendLine(tag + "\t" + item.Value.ToCSVString());
        }

        Debug.LogError(sb.ToString());
        XLogHandler.Write2Console = GameManager.Singleton.OpenLogConsole;

        // send to server
        var deviceModel = SystemInfo.deviceModel;
        var deviceName = SystemInfo.deviceName;
        var deviceType = SystemInfo.deviceType;
        var deviceUniqueIdentifier = SystemInfo.deviceUniqueIdentifier;
        var content = "{" + string.Format("\"deviceName\":\"{0}\",\"deviceModel\":\"{1}\",\"deviceType\":\"{2}\",\"deviceUniqueIdentifier\":\"{3}\",\"profiler\":\"{4}\"",
            deviceName, deviceModel, deviceType, deviceUniqueIdentifier, sb.ToString().Replace("\r", "").Replace("\n", "\\n").Replace("\t", "\\t")) + "}";

        var data = System.Text.Encoding.UTF8.GetBytes(content);
        GameUtils.HttpPost(debugReportUrl, data);
#endif
    }
}
